﻿///////////////////////////////////////////////////////
//
// XDesigner.ORM 
//
// autohr : yuans
//
// date: 2011-2-23
//
// email  : yyf9989@hotmail.com
// 
//
///////////////////////////////////////////////////////

using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel ;

namespace XDesigner.ORM.DOM
{
    [Serializable()]
    public class ORMPropertyInfo : ICloneable
    {
        public ORMPropertyInfo()
        {
        }

        private string _Name = null;
        /// <summary>
        /// Name of property
        /// </summary>
        [DefaultValue( null)]
        public string Name
        {
            get
            {
                return _Name; 
            }
            set
            {
                _Name = value; 
            }
        }

        [NonSerialized()]
        private System.Reflection.PropertyInfo _PropertyInfo = null;
        /// <summary>
        /// Property info 
        /// </summary>
        [Browsable( false )]
        [System.Xml.Serialization.XmlIgnore()]
        public System.Reflection.PropertyInfo PropertyInfo
        {
            get { return _PropertyInfo; }
            set { _PropertyInfo = value; }
        }
        
        [Browsable(false )]
        [System.Xml.Serialization.XmlIgnore()]
        public Type PropertyType
        {
            get
            {
                if (_PropertyInfo == null)
                    return null;
                else
                    return _PropertyInfo.PropertyType;
            }
        }

        private ORMTypeInfo _OwnerType = null;
        [Browsable( false )]
        [System.Xml.Serialization.XmlIgnore()]
        public ORMTypeInfo OwnerType
        {
            get
            {
                return _OwnerType; 
            }
            set
            {
                _OwnerType = value; 
            }
        }
       

        private string _DBFieldName = null;
        /// <summary>
        /// Field name in data base
        /// </summary>
        [DefaultValue(null)]
        public string DBFieldName
        {
            get
            { 
                return _DBFieldName;
            }
            set
            {
                _DBFieldName = value;
            }
        }


        private string _ComparabilityDBFieldName = null;
        /// <summary>
        /// First comparability data base field name
        /// </summary>
        [DefaultValue(null)]
        public string ComparabilityDBFieldName
        {
            get 
            { 
                return _ComparabilityDBFieldName; 
            }
            set
            {
                _ComparabilityDBFieldName = value;
            }
        }

        private string _ComparabilityDBFieldName2 = null;
        /// <summary>
        /// Second comparability data base field name
        /// </summary>
        [DefaultValue(null)]
        public string ComparabilityDBFieldName2
        {
            get
            { 
                return _ComparabilityDBFieldName2; 
            }
            set 
            { 
                _ComparabilityDBFieldName2 = value; 
            }
        }

        internal string RuntimeDBFieldName
        {
            get
            {
                if (Util.HasContent(this.DBFieldName))
                    return this.DBFieldName;
                else
                    return this.Name;
            }
        }

        internal bool MatchDBFieldName(string fieldName)
        {
            if (string.Compare(this.DBFieldName, fieldName, true) == 0)
            {
                return true;
            }
            if (string.Compare(this.ComparabilityDBFieldName, fieldName, true) == 0)
            {
                return true;
            }
            if (string.Compare(this.ComparabilityDBFieldName2, fieldName, true) == 0)
            {
                return true;
            }
            return false;
        }

        private string _Format = null;

        public string Format
        {
            get { return _Format; }
            set { _Format = value; }
        }

        private ORMBooleanValue _ExtCondition = ORMBooleanValue.Default;
        [DefaultValue( ORMBooleanValue.Default )]
        public ORMBooleanValue ExtCondition
        {
            get { return _ExtCondition; }
            set { _ExtCondition = value; }
        }

        private string _Description = null;
        [DefaultValue(null)]
        public string Description
        {
            get
            {
                return _Description; 
            }
            set
            {
                _Description = value; 
            }
        }

        private ORMDBValueType _DBValueType = ORMDBValueType.Default;
        [DefaultValue( ORMDBValueType.Default )]
        public ORMDBValueType DBValueType
        {
            get
            { 
                return _DBValueType;
            }
            set
            {
                _DBValueType = value;
            }
        }

        [System.ComponentModel.Browsable( false )]
        public ORMDBValueType RuntimeDBValueType
        {
            get
            {
                if (_DBValueType == ORMDBValueType.Default)
                {
                    Type t = this.PropertyType;
                    if (t == null)
                    {
                        return ORMDBValueType.Text;
                    }
                    else
                    {
                        if (t.Equals(typeof(string)))
                        {
                            return ORMDBValueType.Text;
                        }
                        else if (t.Equals(typeof(bool))
                            || t.Equals(typeof(byte))
                            || t.Equals(typeof(sbyte))
                            || t.Equals(typeof(short))
                            || t.Equals(typeof(ushort))
                            || t.Equals(typeof(int))
                            || t.Equals(typeof(uint))
                            || t.Equals(typeof(long))
                            || t.Equals(typeof(ulong)))
                        {
                            return ORMDBValueType.Integer;
                        }
                        else if (t.Equals(typeof(decimal))
                           || t.Equals(typeof(float))
                           || t.Equals(typeof(double)))
                        {
                            return ORMDBValueType.Numeric;
                        }
                        else if (t.Equals(typeof(DateTime)))
                        {
                            return ORMDBValueType.DateTime;
                        }
                        else if (t.Equals(typeof(byte[])))
                        {
                            return ORMDBValueType.Binary;
                        }
                        else
                        {
                            return ORMDBValueType.Text;
                        }
                    }
                }
                else
                {
                    return _DBValueType;
                }
            }//get
        }

        private bool _KeyField = false;
        /// <summary>
        /// Is a key field
        /// </summary>
        [DefaultValue(false)]
        public bool KeyField
        {
            get { return _KeyField; }
            set { _KeyField = value; }
        }

        private bool _DelayLoad = false;
        /// <summary>
        /// Is a delay load property
        /// </summary>
        [DefaultValue(false)]
        public bool DelayLoad
        {
            get { return _DelayLoad; }
            set { _DelayLoad = value; }
        }

        private bool _DBReadonly = false;
        /// <summary>
        /// Data base field is readonly
        /// </summary>
        [DefaultValue( false )]
        public bool DBReadonly
        {
            get { return _DBReadonly; }
            set { _DBReadonly = value; }
        }

        private ORMNewValueGenerateInfo _NewValueGenerate = null;
        /// <summary>
        /// Information that specify genereate record key id
        /// </summary>
        [DefaultValue(null)]
        public ORMNewValueGenerateInfo NewValueGenerate
        {
            get { return _NewValueGenerate; }
            set { _NewValueGenerate = value; }
        }

        private string _CommandText = null;
        [DefaultValue(null)]
        public string CommandText
        {
            get { return _CommandText; }
            set
            {
                _CommandText = value;
            }
        }

        private ORMSortStyle _SortStyle = ORMSortStyle.None;
        [DefaultValue( ORMSortStyle.None )]
        public ORMSortStyle SortStyle
        {
            get
            {
                return _SortStyle; 
            }
            set
            {
                _SortStyle = value; 
            }
        }


        private int _SortPriority = 0;
        [DefaultValue(0)]
        public int SortPriority
        {
            get
            {
                return _SortPriority;
            }
            set
            {
                _SortPriority = value;
            }
        }

        [System.ComponentModel.Browsable( false )]
        public bool Overrideable
        {
            get
            {
                if (this.PropertyInfo == null)
                {
                    return false;
                }
                System.Reflection.MethodInfo method = this.PropertyInfo.GetGetMethod();
                if (method.IsVirtual == false || method.IsFinal)
                {
                    return false;
                }
                method = this.PropertyInfo.GetSetMethod();
                if (method.IsVirtual == false || method.IsFinal)
                {
                    return false;
                }
                return true;
            }
        }

        [System.ComponentModel.Browsable( false )]
        internal bool GenerateTemplateValue
        {
            get
            {
                if (this.DelayLoad == false)
                    return false;
                if (this.Relation == null)
                    return false;
                if( Util.IsDBPrimitiveType( this.PropertyType ))
                    return false ;
                ORMRelationStyle rs = this.Relation.RuntimeStyle;
                if (rs == ORMRelationStyle.OneToMany
                    || rs == ORMRelationStyle.OneToManyWithKeyList
                    || rs == ORMRelationStyle.OneToOne )
                {
                    if (this.Relation.ParentProperty == this)
                    {
                        return true;
                    }
                }
                return false;
            }
        }


        private ORMBooleanValue _ParentReference = ORMBooleanValue.Default ;
        [System.ComponentModel.DefaultValue(ORMBooleanValue.Default )]
        public ORMBooleanValue ParentReference
        {
            get { return _ParentReference; }
            set { _ParentReference = value; }
        }
         

        ///// <summary>
        ///// Query command text at runtime
        ///// </summary>
        //public string RuntimeCommandText
        //{
        //    get
        //    {
        //        if (Util.HasContent(this.CommandText))
        //        {
        //            return this.CommandText;
        //        }
        //        else
        //        {
        //            if (this.HasRelation)
        //            {
        //                if (this.OwnerType == null)
        //                {
        //                    throw new InvalidOperationException("Owner is null");
        //                }
        //                Type elementType = this.PropertyType ;
        //                if (this.Relation.Style == ORMRelationStyle.OneToMany)
        //                {
        //                    elementType = CollectionTypeHelper.GetElementType(this.PropertyType);
        //                }
        //                ORMTypeInfo childType = this.OwnerType.Project.Types[ elementType ];
        //                if (childType == null)
        //                {
        //                    throw new InvalidOperationException("childType is null");
        //                }

        //                ORMPropertyInfo parentProperty = this.Relation.ParentProperty;
                        
        //                ORMPropertyInfo childProperty = this.Relation.ChildProperty ;
        //                if (childProperty == null)
        //                {
        //                    throw new InvalidOperationException("child property is null");
        //                }
                        

        //                string strSQL = childType.GetSelectCommandText()
        //                    + " Where " + childProperty.DBFieldName 
        //                    + " = [%@" + parentProperty.Name + "%]";

        //                return strSQL;
        //            }
        //        }
        //        return null;
        //    }
        //}
         

        private bool _Ignore = false;
        /// <summary>
        /// Ignore this property to ORM
        /// </summary>
        [DefaultValue(false)]
        public bool Ignore
        {
            get { return _Ignore; }
            set { _Ignore = value; }
        }

        //private bool _ParentReference = false;
        ///// <summary>
        ///// This property is a reference to parent object
        ///// </summary>
        //[DefaultValue( false )]
        //public bool ParentReference
        //{
        //    get { return _ParentReference; }
        //    set { _ParentReference = value; }
        //}

        private ORMRelationInfo _Relation = null;
        /// <summary>
        /// ORM object relation information
        /// </summary>
        [DefaultValue(null)]
        public ORMRelationInfo Relation
        {
            get
            {
                return _Relation; 
            }
            set
            {
                _Relation = value;
                if (_Relation != null)
                {
                    _Relation.OwnerProperty = this;
                }
            }
        }

        [Browsable( false )]
        public bool HasRelation
        {
            get
            {
                if (_Relation != null)
                {
                    ORMRelationStyle rs = this.Relation.RuntimeStyle;
                    if ( rs == ORMRelationStyle.OneToMany 
                        || rs == ORMRelationStyle.OneToOne
                        || rs == ORMRelationStyle.OneToManyWithKeyList
                        || rs == ORMRelationStyle.OnetoManyExt )
                    {
                        Type t = this.PropertyType;
                        if (t != null)
                        {
                            if (t.IsClass && t.IsPrimitive == false )
                            {
                                return true;
                            }
                        }
                    }
                }
                return false;
            }
        }

        private string _CopyThisReferenceTarget = null;
        [System.ComponentModel.DefaultValue(null)]
        public string CopyThisReferenceTarget
        {
            get { return _CopyThisReferenceTarget; }
            set { _CopyThisReferenceTarget = value; }
        }

        /// <summary>
        /// Detect property value is modified
        /// </summary>
        /// <param name="instance"></param>
        /// <returns></returns>
        public bool IsValueModified(object instance)
        {
            return true;
        }

        object ICloneable.Clone()
        {
            ORMPropertyInfo p = new ORMPropertyInfo();
            p._CommandText = this._CommandText;
            p._DBFieldName = this._DBFieldName;
            p._DelayLoad = this._DelayLoad;
            p._Ignore = this._Ignore;
            p._KeyField = this._KeyField;
            p._Name = this._Name;
            //p._ParentReference = this._ParentReference;
            p._DBReadonly = this._DBReadonly;
            p._ComparabilityDBFieldName = this._ComparabilityDBFieldName;
            p._ComparabilityDBFieldName2 = this._ComparabilityDBFieldName2;
            p._CopyThisReferenceTarget = this._CopyThisReferenceTarget;
            p._Format = this._Format;
            if (this._NewValueGenerate != null)
            {
                p._NewValueGenerate = this._NewValueGenerate.Clone();
            }
            if (this._Relation != null)
            {
                p._Relation = this._Relation.Clone();
            }
            p._ParentReference = this._ParentReference;
            p._SortStyle = this._SortStyle;
            p._SortPriority = this._SortPriority; 
            p._ExtCondition = this._ExtCondition;
            p._DBValueType = this._DBValueType;
            p._Description = this._Description;
            return p;
        }

        public ORMPropertyInfo Clone()
        {
            return (ORMPropertyInfo)((ICloneable)this).Clone();
        }

        public override string ToString()
        {
            if (this.HasRelation)
            {
                Type childType = this.PropertyType ;
                if (this.Relation.Style == ORMRelationStyle.OneToMany)
                {
                    childType = CollectionTypeHelper.GetElementType(childType);
                }
                return this.Name + ":" + this.Relation.Style.ToString() 
                    + "[" + this.Relation.RuntimeParentPropertyName + "->" 
                    + childType.Name + "."
                    + this.Relation.ChildPropertyName +"]";
            }
            if (this.PropertyInfo == null)
            {
                return this.Name;
            }
            else
            {
                return this.PropertyInfo.Name + "->" + this.DBFieldName ;
            }
        }
          
    }

    [System.Diagnostics.DebuggerDisplay("ORMPropertyList Count={ Count }")]
    [System.Diagnostics.DebuggerTypeProxy(typeof(ORMDebugView))]
    public class ORMPropertyInfoList : System.Collections.CollectionBase
    {
        public ORMPropertyInfoList()
        {
        }

        public ORMPropertyInfo this[int index]
        {
            get
            {
                return (ORMPropertyInfo)this.List[index];
            }
        }

        public ORMPropertyInfo this[string name]
        {
            get
            {
                foreach (ORMPropertyInfo item in this)
                {
                    if (string.Compare(item.Name, name, true) == 0)
                    {
                        return item;
                    }
                }
                return null;
            }
        }

        public ORMPropertyInfo GetByDBFieldName(string name)
        {
            foreach (ORMPropertyInfo item in this)
            {
                if (string.Compare(item.DBFieldName, name, true) == 0)
                {
                    return item;
                }
            }
            return null;
        }

        public ORMPropertyInfo GetByName(string name)
        {
            if (name == null)
            {
                return null;
            }
            name = name.Trim();
            foreach (ORMPropertyInfo item in this)
            {
                if (string.Compare(item.Name, name, true) == 0)
                {
                    return item;
                }
            }
            foreach (ORMPropertyInfo item in this)
            {
                if (string.Compare(item.DBFieldName, name, true) == 0)
                {
                    return item;
                }
            }
            return null;
        }

        public int Add(ORMPropertyInfo item)
        {
            return this.List.Add(item);
        }

        public void Remove(ORMPropertyInfo item)
        {
            this.List.Remove(item);
        }
    }

}
